import Orinheapq, tempfile, datetime, AdvOrinheapq
from hashlib import md5
## Add AdvOrinheapq for special Sort ###

class swpSort:
	def __init__(self, buffLine, tmpdir=False):
		''' buffLine is line number of each block file.
 tmpdir: when specified, block files will be generated in such dir, default is /tmp/.
		'''

		if tmpdir:
			self.__tmpdir = tmpdir
			tempfile.tempdir = self.__tmpdir
		self.buffLine = buffLine
		self.swpfunc = {True:self.swpSort, False:self.swpSort_single}
		self.__nowSwpFile = {}
		#self.__sType = {False:Orinheapq.mergeList,True:Orinheapq.mergeSingle}
		self.intJudge = {0:str,1:int}
		self.__sType = {False:Orinheapq.mergeList,True:Orinheapq.merge}
		self.__sTypeAdv = {False:AdvOrinheapq.mergeList,True:AdvOrinheapq.merge}


	def GetTimeMD5(self):
		return md5(str(datetime.datetime.now())).hexdigest()

	def AssignFile(self,FHash):
		''' FHash is filehandle hash, key=filename, value = filehandle '''

		### ATTENTION: this is not a deep copy!!! ###
		self.__nowSwpFile = FHash

	def mainSplit(self,fH,sKey):
		tmpArray = []
		tmpCount = 0
		tmpFile = self.GetTimeMD5()
		for lines in fH:
			lineArray = lines.strip().split('\t')
			if len(lineArray) <= max(sKey): continue
			if not lineArray: continue
			#tmpArray.append(map(lambda x: lineArray[int(x)], sKey))
			tmpArray.append(lineArray)
			tmpCount += 1
			if tmpCount > self.buffLine*10000:
				self.swpfunc[len(sKey)>1](tmpArray,sKey,str(tmpFile))
				tmpCount = 0
				del tmpArray
				tmpArray=[]
				tmpFile = self.GetTimeMD5()
		else:
			if tmpCount:
				self.swpfunc[len(sKey)>1](tmpArray,sKey,str(tmpFile))
				tmpCount = 0
				del tmpArray,tmpFile

	def swpSort(self,toSort,sKey,fH):
		self.__nowSwpFile[fH] = tempfile.TemporaryFile()
		for line in sorted(toSort, key=lambda y: map(lambda x:self.intJudge[y[int(x)].isdigit()](y[int(x)]), sKey)):
			#print ":\t:".join(line)
			self.__nowSwpFile[fH].write("\t".join(line))
			self.__nowSwpFile[fH].write("\n")
		self.__nowSwpFile[fH].seek(0)

	def swpSort_single(self,toSort,sKey,fH):
		self.__nowSwpFile[fH] = tempfile.TemporaryFile()
		for line in sorted(toSort, key=lambda y: map(lambda x:self.intJudge[y[int(x)].isdigit()](y[int(x)]), sKey)):
			#print ":\t:".join(line)
			self.__nowSwpFile[fH].write("\t".join(line))
			self.__nowSwpFile[fH].write("\n")
		self.__nowSwpFile[fH].seek(0)

	def MergSort(self, skey=(), Adv=False):
		''' Generate a sorted filehandle with FMT: SortedKey\tFreq of it\n.'''

		FuncHash = {}
		f = tempfile.TemporaryFile()
		KTMP = {}
		if Adv:
			FuncHash.update(self.__sTypeAdv)
		else:
			FuncHash.update(self.__sType)
		#for x in self.__sType[(len(sKey) == 1)](sKey, self.__nowSwpFile.values()):
		#for x in self.__sType[(len(sKey) == 1)](self.__nowSwpFile.values()):

		###########################################################################
		# All in Tempfile is exact farmat, so sKey is never needed.--------Ver 1.0#
		###########################################################################

		###################################################################################
		# Sometime the original files were generated already, we need sorted by specified #
		# area, so we add skey. -----------------Ver 2.0                                  #
		###################################################################################

		#for x in self.__sType[len(skey) < 1](skey, self.__nowSwpFile.values()):
		for x in FuncHash[len(skey) < 1](skey, self.__nowSwpFile.values()):
			#print '%s:' % x
		#for x in Orinheapq.mergeList(skey, self.__nowSwpFile.values()):
			if KTMP:
				if KTMP.has_key(x):
					KTMP[x] += 1
					continue
				else:
#					if x.strip() == '86017819':
#						print ':%s:' % x
#						print '%s\t%s' % (x,KTMP.keys()[0])
					f.write("%s\t%d\n" % (KTMP.keys()[0], KTMP.values()[0]))
					KTMP.clear()
					KTMP[x] = 1
			else:
				KTMP[x] = 1
		else:
			if KTMP:
				f.write("%s\t%d\n" % (KTMP.keys()[0], KTMP.values()[0]))
				KTMP.clear()
		f.seek(0)
		map(lambda x: x.close(),self.__nowSwpFile.values())
		self.__nowSwpFile.clear()
		FuncHash.clear()
		return f
